/*----------------    FILE HEADER  ------------------------------------------

This file is part of monogis.
Copyright (C) 2004-2006 by: http://sourceforge.net/projects/mgis


This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA             
---------------------------------------------------------------------------*/

/*-------------- Original license ------------------------------------------
The monoGIS GDAL driver is a collection of .NET classes written in C# that
implement the fundamental P/Invoke operations required to treat 
geo-spatial data using Frank Wamerdam's GDAL C++ library.

This collection of classes is a porting (with some additions and modifications) of
code that has been sent to the gdal-dev mailing list (gdal-dev@lists.maptools.org). 
We want especially thank to:
- Simon Perkins, for contributing his GDAL_csharp library to gdal-dev:
------ GDAL_csharp "license" ---
"This partial implementation is good enough for my needs now. If anyone 
else wants to use it, please feel free. If you want to extend it and 
send updates to me, great! The code doesn't contain any explcit licence 
headers, but Michael was suggesting an MIT licence, same as GDAL. Fine 
with me.

Cheers,

Sy"

 * ------ GDAL_csharp "license" ---
- Morton Nielsen, for contributing code to the gdal-dev:
"
Great work on the .NET wrappers. I decided to take it a step further and putting it all
in some nice classes, so you won't have to worry about pointers, disposing objects etc.
I think a lot of .NET developers would like that approach. 
I put the code example for download here:
     http://www.iter.dk/dotnet/gdal/gdal_test.zip

I added some code-comments copied from the gdal website as well, 
so you will have intellisence on most of the methods.
"
------ gdal_test "license" ----------------------------------------------------
 * ---------------------------------

Copyright (c) 2005 Morten Nielsen

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal 
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all 
copies of this Software or works derived from this Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.

------ gdal_test "license" ------------------------------------------------------


 
Copy of GDAL/OGR license:
  Copyright (c) 2000, Frank Warmerdam

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. 
---------------------------------------------------------------------------*/
using System;
using System.Text;
using System.Runtime.InteropServices;


namespace Gdal
{
    public enum RWFlag
    {
        Read = 0,
        Write = 1
    }

    public enum DataType
    {
        Unknown = 0,
        Byte = 1,
        UInt16 = 2,
        Int16 = 3,
        UInt32 = 4,
        Int32 = 5,
        Float32 = 6,
        Float64 = 7,
        CInt16 = 8,
        CInt32 = 9,
        CFloat32 = 10,
        CFloat64 = 11,
        TypeCount = 12
    }

    /// <summary>
    /// Types of color interpretation for raster bands.
    /// </summary>
    public enum ColorInterp
    {
        Undefined = 0,
        /// <summary>
        /// Greyscale
        /// </summary>
        GrayIndex = 1,
        /// <summary>
        /// Paletted (see associated color table)
        /// </summary>
        PaletteIndex = 2,
        /// <summary>
        /// Red band of RGBA image
        /// </summary>               
        RedBand = 3,
        /// <summary>
        /// Green band of RGBA image
        /// </summary>
        GreenBand = 4,
        /// <summary>
        /// Blue band of RGBA image
        /// </summary>                       
        BlueBand = 5,
        /// <summary>
        /// Alpha (0=transparent, 255=opaque)
        /// </summary>   
        AlphaBand = 6,
        /// <summary>
        /// Hue band of HLS image 
        /// </summary>                 
        HueBand = 7,
        /// <summary>
        /// Saturation band of HLS image 
        /// </summary>       
        SaturationBand = 8,
        /// <summary>
        /// Lightness band of HLS image
        /// </summary>            
        LightnessBand = 9,
        /// <summary>
        /// Cyan band of CMYK image
        /// </summary>                
        CyanBand = 10,
        /// <summary>
        /// Magenta band of CMYK image
        /// </summary>             
        MagentaBand = 11,
        /// <summary>
        /// Yellow band of CMYK image
        /// </summary>             
        YellowBand = 12,
        /// <summary>
        /// Black band of CMYK image
        /// </summary>                      
        BlackBand = 13,
        /// <summary>
        /// Y Luminance
        /// </summary>                             
        YCbCr_YBand = 14,
        /// <summary>
        /// Cb Chroma
        /// </summary>                              
        YCbCr_CbBand = 15,
        /// <summary>
        /// Cr Chroma
        /// </summary>                                          
        YCbCr_CrBand = 16,
        /*! Max current value */
        Max = 16
    } ;

    public class RasterBand
    {
        internal HandleRef hBand;

        internal RasterBand(IntPtr ptrBand)
        {
            hBand = new HandleRef(this, ptrBand);
        }

        /// <summary>
        /// Read or write a block of data from/to a RasterBand. The data type of the buffer is automatically
        /// converted to that of the image file if necessary, and resampling is performed as necessary to
        /// match the buffer dimensions to the requested rectangle. The buffer is passed in as an IntPtr.
        /// This method allows for non-standard pixel and line strides to be specified.
        /// </summary>
        /// <param name="flag">Set to RWFlag.Read to read from the file, or RWFlag.Write to write
        /// to the file.</param>
        /// <param name="xOff">The x coordinate of the top left corner of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="yOff">The y coordinate of the top left corner of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="xSize">The width of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="ySize">The height of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="buffer">A pointer to an in memory buffer.</param>
        /// <param name="bufXSize">The width of the buffer in pixels.</param>
        /// <param name="bufYSize">The height of the buffer in pixels.</param>
        /// <param name="dataType">The type of the data within the buffer.</param>
        /// <param name="pixelStride">The byte offset from the start of one pixel in the buffer
        /// to the start of the next pixel. If zero, defaults to the size of the specified data type.</param>
        /// <param name="lineStride">The byte offset from the start of one scanline in the buffer
        /// to the start of the next scanline. If zero, defaults to the size of the specified data type, times
        /// the buffer width.</param>
        public void RasterIO(RWFlag flag, int xOff, int yOff, int xSize, int ySize,
            IntPtr buffer, int bufXSize, int bufYSize, DataType dataType, int pixelStride, int lineStride)
        {
            if (InterOp.GDALRasterIO(hBand, flag, xOff, yOff, xSize, ySize,
                    buffer, bufXSize, bufYSize, dataType, pixelStride, lineStride) != CPLErr.None)
                throw new ApplicationException("Error while reading raster file\n" + InterOp.CPLGetLastErrorMsg());
        }

        /// <summary>
        /// Read or write a block of data from/to a RasterBand. The data type of the buffer is automatically
        /// converted to that of the image file if necessary, and resampling is performed as necessary to
        /// match the buffer dimensions to the requested rectangle. The buffer is passed in as an IntPtr.
        /// </summary>
        /// <param name="flag">Set to RWFlag.Read to read from the file, or RWFlag.Write to write
        /// to the file.</param>
        /// <param name="xOff">The x coordinate of the top left corner of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="yOff">The y coordinate of the top left corner of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="xSize">The width of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="ySize">The height of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="buffer">A pointer to an in memory buffer.</param>
        /// <param name="bufXSize">The width of the buffer in pixels.</param>
        /// <param name="bufYSize">The height of the buffer in pixels.</param>
        /// <param name="dataType">The type of the data within the buffer.</param>
        public void RasterIO(RWFlag flag, int xOff, int yOff, int xSize, int ySize,
            IntPtr buffer, int bufXSize, int bufYSize, DataType dataType)
        {
            if (InterOp.GDALRasterIO(hBand, flag, xOff, yOff, xSize, ySize,
                    buffer, bufXSize, bufYSize, dataType, 0, 0) != CPLErr.None)
                throw new ApplicationException("Error while reading raster file\n" + InterOp.CPLGetLastErrorMsg());
        }

        /// <summary>
        /// Read or write a block of data from/to a RasterBand. The data type of the buffer is automatically
        /// converted to that of the image file if necessary, and resampling is performed as necessary to
        /// match the buffer dimensions to the requested rectangle. The buffer is passed in as an array of bytes.
        /// </summary>
        /// <param name="flag">Set to RWFlag.Read to read from the file, or RWFlag.Write to write
        /// to the file.</param>
        /// <param name="xOff">The x coordinate of the top left corner of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="yOff">The y coordinate of the top left corner of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="xSize">The width of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="ySize">The height of the rectangular region of 
        /// the image to be read/written.</param>
        /// <param name="buffer">An array of bytes actings as a buffer.</param>
        /// <param name="bufXSize">The width of the buffer in pixels.</param>
        /// <param name="bufYSize">The height of the buffer in pixels.</param>
        public unsafe void RasterIO(RWFlag flag, int xOff, int yOff, int xSize, int ySize,
            byte[] buffer, int bufXSize, int bufYSize)
        {
            fixed (byte* bufPtr = buffer) {
                if (InterOp.GDALRasterIO(hBand, flag, xOff, yOff, xSize, ySize,
                        new IntPtr(bufPtr), bufXSize, bufYSize, DataType.Byte, 0, 0) != CPLErr.None)
                    throw new ApplicationException("Error while reading raster file\n" + InterOp.CPLGetLastErrorMsg());
            }
        }

        /// <summary>
        /// Get the color interpretation of this band.
        /// </summary>
        public ColorInterp ColorInterpretation
        {
            get
            {
                return (ColorInterp)InterOp.GDALGetRasterColorInterpretation(hBand);
            }
        }

    }
}
